package com.github.byakkili.bim.core.handler.command;

import com.github.byakkili.bim.core.BimSession;
import com.github.byakkili.bim.core.listener.SessionListener;
import lombok.AllArgsConstructor;

import java.util.Map;

/**
 * @author Guannian Li
 */
@AllArgsConstructor
public class CommandRunnable implements Runnable {
    private final BimSession session;
    private final CommandFrame reqFrame;
    private final CommandHandler commandHandler;
    private final Map<Integer, CommandProcessor> commandProcessors;

    CommandRunnable(BimSession session, CommandFrame reqFrame, CommandHandler commandHandler) {
        this.session = session;
        this.reqFrame = reqFrame;
        this.commandHandler = commandHandler;
        this.commandProcessors = session.getContext().getConfig().getCommandProcessors();
    }

    @Override
    public void run() {
        RuntimeException tmpEx = null;
        CommandFrame respFrame = null;
        Integer command = reqFrame.getCommand();
        try {
            if (!commandHandler.applyPreHandle(reqFrame, session)) {
                return;
            }
            @SuppressWarnings("unchecked")
            CommandProcessor<Object, Object> commandProcessor = this.commandProcessors.get(command);
            if (commandProcessor == null) {
                return;
            }
            Object msg = reqFrame.getMessage();
            respFrame = commandProcessor.handle(msg, session);
            commandHandler.applyPostHandle(reqFrame, respFrame, session);
        } catch (RuntimeException ex) {
            tmpEx = ex;
            throw ex;
        } finally {
            commandHandler.triggerAfterCompletion(reqFrame, session, tmpEx);
            if (respFrame != null) {
                session.writeAndFlush(respFrame);
            }
        }
    }
}
